package com.zu.commu.insertDataServletXml.localOperate;

import com.zu.commu.context.ServerContext;
import com.zu.commu.util.DateTime;
import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.XMLOutputter;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

public class XmlOperator {
	private static Object synObj = new Object();

	private static XmlOperator instance = null;

	private static String dirrName = ServerContext.xmlFileDir;

	private static int totalDate = ServerContext.localSaveDate;

	private static String initXml = null;

	private static String dataEleName = "datas";
	private static String dataEleStamp = "stamp";

	static {
		if ((!dirrName.endsWith("\\")) && (!dirrName.endsWith("/"))) {
			dirrName += "/";
		}

		initXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
		initXml += "<datum>\n";
		initXml += "</datum>\n";
	}

	public static XmlOperator instance() {
		if (instance == null) {
			instance = new XmlOperator();
		}
		return instance;
	}

	public void saveXmlData(String xml) {
		synchronized (synObj) {
			File f = getCurrenTimeFile();
			if (f.exists()) {
				SAXBuilder sb = new SAXBuilder();
				try {
					Document doc = sb.build(new FileInputStream(f));
					Element root = doc.getRootElement();
					if (root == null) {
						Logger log = Logger.getLogger(XmlOperator.class
								.getName());
						log.error("本地保存数据的文件得到根元素发生异常！");
					}
					Element data = new Element(dataEleName);
					String stamp = DateTime.getYear() + DateTime.getMonth()
							+ DateTime.getDate() + DateTime.getHour()
							+ DateTime.getMinute() + DateTime.getSecond();
					data.setAttribute(dataEleStamp, stamp);
					root.addContent(data);
					xml = xml.replaceAll("<", "@");
					xml = xml.replaceAll(">", "#");
					data.addContent(xml);
					saveXML(doc, f);
				} catch (Exception e) {
					Logger log = Logger.getLogger(XmlOperator.class.getName());
					log.error("由本地保存数据的文件创建文档对象出生异常！");
				}
			} else {
				Logger log = Logger.getLogger(XmlOperator.class.getName());
				log.error("没有得到本地保存数据的文件！");
			}
		}
	}

	public String[] getXmlData(String year, String month, String date,
			String hour, String minute, String second) {
		synchronized (synObj) {
			int n = 0;
			while (n < totalDate + 1) {
				n++;
				File[] allDir = getAllDataDir();
				if ((allDir == null) || (allDir.length == 0)) {
					return null;
				}
				File oldestDir = getOldestDateDir(allDir);
				File oldestFile = getOldestFile(oldestDir);
				if (oldestFile == null) {
					deleteDir(oldestDir);
				} else {
					String stamp = year + month + date + hour + minute + second;
					String[] datas = getXmlData(oldestFile, stamp);
					if ((datas == null) || (datas.length == 0)) {
						deleteFile(oldestFile);
					} else {
						deleteFile(oldestFile);
						return datas;
					}
				}
			}
		}
		return null;
	}

	private void saveXML(Document doc, File xmlFile) {
		try {
			XMLOutputter outp = new XMLOutputter();
			outp.output(doc, new FileOutputStream(xmlFile));
		} catch (Exception e) {
			e.printStackTrace();
			Logger log = Logger.getLogger(XmlOperator.class.getName());
			log.error("本地保存数据到xml文件操作出生异常！" + e.getMessage());
		}
	}

	private String[] getXmlData(File xmlFile, String stamp) {
		String[] r = (String[]) null;
		try {
			SAXBuilder sb = new SAXBuilder();
			Document doc = sb.build(new FileInputStream(xmlFile));
			Element root = doc.getRootElement();
			if (root == null) {
				Logger log = Logger.getLogger(XmlOperator.class.getName());
				log.error("本地保存数据的文件格式不合法，此文件将被强制删除！");
				return null;
			}
			List list = root.getChildren();
			if ((list == null) || (list.isEmpty())) {
				return null;
			}
			r = new String[list.size()];
			int n = 0;
			String xmlData = null;
			Iterator it = list.iterator();
			Element datas = null;
			boolean ok = true;
			while (it.hasNext()) {
				ok = true;
				datas = (Element) (Element) it.next();
				String dstamp = datas.getAttributeValue(dataEleStamp);
				try {
					if (Integer.parseInt(dstamp) < Integer.parseInt(stamp)) {
						ok = false;
					}
				} catch (Exception e) {
					ok = false;
				} finally {
					if (ok) {
						xmlData = datas.getText();
						xmlData = xmlData.replaceAll("@", "<");
						xmlData = xmlData.replaceAll("#", ">");
						r[n] = xmlData;
						n++;
					}
				}
			}
		} catch (Exception e) {
			Logger log = Logger.getLogger(XmlOperator.class.getName());
			log.error("本地保存数据的文件格式不合法，此文件将被强制删除！");
		}
		return r;
	}

	private File getCurrenTimeFile() {
		File f = null;
		File dir = getCurrenDateDir();
		if (dir == null) {
			Logger log = Logger.getLogger(XmlOperator.class.getName());
			log.error("没有得到本地保存数据的文件夹路径！");
			return null;
		}
		String fileName = currenDateTimeFileName();
		File[] ff = dir.listFiles();
		for (int i = 0; i < ff.length; i++) {
			if (ff[i].getName().equals(fileName)) {
				f = ff[i];
				break;
			}
		}
		if (f == null) {
			f = new File(dir.getPath() + "/" + fileName);
			try {
				FileOutputStream ou = new FileOutputStream(f);

				ou.write(initXml.getBytes());
				ou.flush();
				ou.close();
			} catch (Exception localException) {
			}
		}
		return f;
	}

	private File getOldestFile(File dir) {
		File[] ff = dir.listFiles();
		if ((ff == null) || (ff.length == 0)) {
			return null;
		}
		ff = sortDir(ff);
		return ff[0];
	}

	private void deleteDir(File dir) {
		dir.delete();
	}

	private void deleteFile(File file) {
		file.delete();
	}

	private File getCurrenDateDir() {
		File dir = null;
		File dirr = new File(dirrName);
		File[] ff = dirr.listFiles();

		String curDirName = currenDateDirName();

		for (int i = 0; i < ff.length; i++) {
			if (ff[i].getName().equals(curDirName)) {
				dir = ff[i];
			}

		}

		if (dir == null) {
			dir = dirOperate(curDirName);
		}

		return dir;
	}

	public File[] getAllDataDir() {
		File dirr = new File(dirrName);
		File[] ff = dirr.listFiles();
		return ff;
	}

	private File getOldestDateDir(File[] ff) {
		ff = sortDir(ff);
		return ff[0];
	}

	public File dirOperate(String curDirName) {
		File dir = new File(dirrName + curDirName);
		dir.mkdir();
		File dirr = new File(dirrName);
		File[] ff = dirr.listFiles();
		if (ff.length > totalDate) {
			ff = sortDir(ff);
			File[] fff = (File[]) null;
			for (int i = 0; i < ff.length - totalDate; i++) {
				fff = ff[i].listFiles();
				if (fff != null) {
					for (int j = 0; j < fff.length; j++) {
						fff[j].delete();
					}
				}
				ff[i].delete();
			}
		}
		return dir;
	}

	private String currenDateDirName() {
		return new SimpleDateFormat("yyyyMMdd").format(new Date(System
				.currentTimeMillis()));
	}

	private String currenDateTimeFileName() {
		return new SimpleDateFormat("yyyyMMddHH").format(new Date(System
				.currentTimeMillis())) + ".xml";
	}

	private File[] sortDir(File[] ff) {
		if (ff == null) {
			return null;
		}
		File temp = null;
		boolean change = true;

		int n = ff.length;
		int m = 1;
		while (n > 1) {
			if (!change) {
				break;
			}
			change = false;
			while (m < n) {
				if (isOneBigTwo(ff[(m - 1)].getName(), ff[m].getName())) {
					change = true;
					temp = ff[(m - 1)];
					ff[(m - 1)] = ff[m];
					ff[m] = temp;
				}
				m++;
			}
			n--;
			m = 1;
		}

		return ff;
	}

	private boolean isOneBigTwo(String one, String two) {
		int i = one.compareTo(two);

		return i > 0;
	}
}
